package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
	"strconv"
	"time"
)

const (
	TransactionKeyPrefix  = "transaction"
	TxStatusNew           = "新建（待确认）"
	TxStatusConfirm       = "新建（已确认）"
	TxStatusPayForAnother = "申请代付"
	TxStatusPay           = "已付款（未核实）"
	TxStatusPayed         = "已付款（已核实）"
	TxStatusRefusePay     = "代付被拒"
	TxStatusShip          = "已发货（未核实）"
	TxstatusShiped        = "已发货（已核实）"
	TxStatusRepay         = "已还款（未核实）"
	TxStatusRepayed       = "已还款（已核实）"
)

type SupplyChainFinance struct {
}

// 	新建 -> 已确认 -> 申请代付 -> 已付款 ->确认付款-> 已发货 -> 确认发货 -> 已还款 -> 确认已还款
//                       |
//                    拒绝付款 ->回到上一步
type Transaction struct {
	Id                string    `json:"id"`                  // 单号
	Description       string    `json:"description"`         // 备注
	Value             uint64    `json:"value"`               // 金额(单位为一分钱)
	ShipmentNumber    string    `json:"shipment_number"`     // 物流号
	PaymentTxNumber   string    `json:"payment_tx_number"`   // 付款转账号
	RepaymentTxNumber string    `json:"repayment_tx_number"` // 还款转账号
	Status            string    `json:"status"`              // 订单状态      ----请使用上面const中的常量来标记订单状态
	CreateDate        time.Time `json:"create_date"`         // 创建时间
	PaymentDate       time.Time `json:"payment_date"`        // 付款时间
	RepaymentDate     time.Time `json:"repayment_date"`      // 应还款时间
	RepayDate         time.Time `json:"repay_date"`          // 实际还款时间
	Supplier          string    `json:"supplier"`            // 供应商
	Company           string    `json:"company"`             // 采购商
	FinancialOrg      string    `json:"financial_org"`       // 金融机构
}

type Company struct {
	Name           string    `json:"name"`            //企业名
	Phone          string    `json:"phone"`           //联系电话
	Account        string    `json:"account"`         //登录账号
	Password       string    `json:"password"`        //登录密码
	Address        string    `json:"address"`         //地址
	CompanyType    string    `json:"company_type"`    //企业类型，供应商，采购商，金融机构
	EnterpriseCode string    `json:"enterprise_code"` //企业统一社会信用代码
	BankCard       string    `json:"bank_card"`       //银行卡号码
	Balance        uint64    `json:"balance"`         //余额
	CreateDate     time.Time `json:"create_date"`     //创建时间
}

// 企业的3种类型
var companyArg = map[string]string{"financial_org": "financial_org", "supplier": "supplier", "buyer": "buyer"}


/**
  @Author: dd
  @Date:   2020/5/13 16:22
  @Desc:   智能合约初始化，要求必须创建3个企业，分别为供应商、采购商、金融企业 ,Company.Name="datainsights" （必需） *
  @Param:
  @Return:
**/
func(s *SupplyChainFinance)Init(stub shim.ChaincodeStubInterface) pb.Response{
	for _,v := range companyArg{
		copany := &Company{
			Name:           "datainsights",
			Phone:          "123",
			Account:        "123",
			Password:       "123",
			Address:        "China",
			CompanyType:    v,
			EnterpriseCode: "12312",
			BankCard:       "123123",
			Balance:        1000,
			CreateDate:     time.Now(),
		}
		companybyte,err := json.Marshal(copany)
		if err != nil {
			return shim.Error("marshal error")
		}
		res := createCompany(stub,[]string{string(companybyte)})
		if res.Status != shim.OK {
			return shim.Error(res.Message)
		}
	}
	return shim.Success(nil)
}

func(s *SupplyChainFinance)Invoke(stub shim.ChaincodeStubInterface) pb.Response{
	fcn,args := stub.GetFunctionAndParameters()
	switch fcn {
	//创建用户
	case "createCompany":
		return createCompany(stub,args)
	//	创建订单
	case "newTransaction":
		return newTransaction(stub,args)
	//	确认订单
	case "confirmTransaction":
		return confirmTransaction(stub,args)
	//	申请代付
	case "applyPayForAnother":
		return applyPayForAnother(stub,args)
	//	支付订单
	case "payTransaction":
		return payTransaction(stub,args)
	//	供应商确认收款
	case "affirmPay":
		return affirmPay(stub,args)
	//	拒绝代付
	case "refusePayTransaction":
		return refusePayTransaction(stub,args)
	//	供应商发货
	case "updateShipmentInfo":
		return updateShipmentInfo(stub,args)
	//	买方还款
	case "repayTransaction":
		return repayTransaction(stub,args)
	//	金融机构确认还款
	case "verifyRepay":
		return verifyRepay(stub,args)
	//	自动检测还款
	case "autoRepay":
		return autoRepay(stub,args)
	//	获取用户订单记录
	case "getTrByBuyer":
		return getTrByBuyer(stub,args)
	//	获取用户
	case "getCompany":
		return getCompany(stub,args)
	//	获取订单
	case "getTransactions":
		return getTransactions(stub,args)
	//	获取订单历史
	case "getTransactionHistory":
		return getTransactionHistory(stub,args)
	//	采购商确认发货
	case "verifyShipmentInfo":
		return verifyShipmentInfo(stub,args)


	default:
		return shim.Error("doesn't exist this fcn")
	}
}

/**
  @Author: dd
  @Date:   2020/5/13 16:48
  @Desc:   根据company.CompanyType来创建3种不同的企业*
  @Param:  Company
  @Return: res = peer.Response,       要求返回结果时能够返回正确相应的响应码：shim.ERROR,shim.ERRORTHRESHOLD,shim.OK
**/
func createCompany(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	var res pb.Response
	res.Status = shim.ERRORTHRESHOLD
	if len(args) != 1 {
		return res
	}
	var company Company
	if err := json.Unmarshal([]byte(args[0]),&company);err != nil {
		return shim.Error("unmarshal error")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(company.CompanyType,[]string{company.Name})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) != 0 {
		return shim.Error("this company already exist")
	}
	//序列化值
	companybytes,err := json.Marshal(company)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:01
  @Desc:   创建新的交易 *
  @Param:  {id:string, Value:int, supplier:string, create_date:time.Time, company:string}
  @Return:
**/
func newTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == "" || transation.Value == 0 || transation.Supplier == "" || transation.CreateDate.IsZero() || transation.Company == "" {
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) != 0 {
		return shim.Error("this transation already exist")
	}
	//检测用户是否存在
	if !valideCompany(stub,"buyer",transation.Company) || ! valideCompany(stub,"supplier",transation.Supplier){
		return shim.Error("company does't exist")
	}
	//修改状态
	transation.Status = TxStatusNew
	//序列化值
	companybytes,err := json.Marshal(transation)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:00
  @Desc:   供应商确认交易 *
  @Param:  {id:string, supplier:string}
  @Return:
**/
func confirmTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.Supplier == "" {
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.Supplier != tx.Supplier{
		return shim.Error("error company")
	}
	tx.Status = TxStatusConfirm
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}


/**
  @Author: dd
  @Date:   2020/5/15 17:57
  @Desc:   向金融机构申请代付 *
  @Param:  {id:string, company:string, financial_org:string, repayment_date:time.Time}
  @Return:
**/
func applyPayForAnother(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.Company == "" ||transation.FinancialOrg == "" || transation.RepaymentDate.IsZero(){
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//检测用户是否存在
	if ! valideCompany(stub,"financial_org",transation.FinancialOrg){
		return shim.Error("company does't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.Company != tx.Company{
		return shim.Error("error company")
	}
	tx.RepaymentDate = transation.RepaymentDate
	tx.FinancialOrg = transation.FinancialOrg
	tx.Status = TxStatusPayForAnother
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:57
  @Desc:   付款  *
  @Param:  {id:string,PaymentTxNumber:string,financial_org:string,payment_date:time.Time}
  @Return:
**/
func payTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.PaymentTxNumber == "" || transation.FinancialOrg == "" || transation.PaymentDate.IsZero(){
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.FinancialOrg != tx.FinancialOrg{
		return shim.Error("error company")
	}
	tx.PaymentDate = transation.PaymentDate
	tx.PaymentTxNumber = transation.PaymentTxNumber
	tx.Status = TxStatusPay
	//检测是否转账成功
	res := transferAccounts(stub,transation.FinancialOrg,"financial_org",transation.Supplier,"supplier",transation.Value)
	if res.Status != shim.OK {
		return shim.Error(res.Message)
	}
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:00
  @Desc:   供应商核实付款 *
  @Param:  {id:string, supplier:string}
  @Return:
**/
func affirmPay(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.Supplier == "" {
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.Supplier != tx.Supplier{
		return shim.Error("error company")
	}
	tx.Status = TxStatusPayed
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:55
  @Desc:   拒绝付款要求  *
  @Param:  {id:string,description:string,financial_org:string}
  @Return:
**/
func refusePayTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.Description == ""|| transation.FinancialOrg == "" {
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.FinancialOrg != tx.FinancialOrg{
		return shim.Error("error company")
	}
	tx.Description = transation.Description
	tx.Status = TxStatusRefusePay
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:54
  @Desc:   供应商发货  *
  @Param:  {id:string,shipment_number:string,supplier:string}
  @Return:
**/
func updateShipmentInfo(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.Supplier == "" || transation.ShipmentNumber == ""{
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.Supplier != tx.Supplier{
		return shim.Error("error company")
	}
	tx.ShipmentNumber = transation.ShipmentNumber
	tx.Status = TxStatusShip
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:53
  @Desc:   买方收货  *
  @Param:  {id:string,company:string}
  @Return:
**/
func verifyShipmentInfo(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.Company == "" {
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.Company != tx.Company{
		return shim.Error("error company")
	}
	tx.Status = TxstatusShiped
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:50
  @Desc:   买方还款  *
  @Param:  {id:string,repayment_tx_number:string,tx_to_update:time.Time,company:string}
  @Return:
**/
func repayTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.RepaymentTxNumber == "" || transation.RepayDate.IsZero() || transation.Company == ""{
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.Company != tx.Company{
		return shim.Error("error company")
	}
	tx.RepayDate = transation.RepayDate
	tx.RepaymentTxNumber = tx.RepaymentTxNumber
	tx.Status = TxStatusRepay
	//检测是否转账成功
	res := transferAccounts(stub,transation.Company,"buyer",transation.FinancialOrg,"financial_org",transation.Value)
	if res.Status != shim.OK {
		return shim.Error(res.Message)
	}
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:48
  @Desc:   金融机构确认还款  *
  @Param:  {id:string,financial_org:string}
  @Return:
**/
func verifyRepay(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	var transation Transaction
	if err := json.Unmarshal([]byte(args[0]),&transation);err != nil {
		return shim.Error("unmarshal error")
	}
	if transation.Id == ""  || transation.FinancialOrg == "" {
		return shim.Error("invalid args")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
	if err != nil {
		return shim.Error("createCompisteKey error")
	}
	//从账本获取值
	bytes,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytes) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//修改状态
	var tx Transaction
	if err := json.Unmarshal(bytes,&tx);err != nil {
		return shim.Error("unamrshal error")
	}
	//检测是否为同一公司
	if transation.FinancialOrg != tx.FinancialOrg{
		return shim.Error("error company")
	}
	tx.Status = TxStatusRepayed
	//序列化值
	companybytes,err := json.Marshal(tx)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(compositeKey,companybytes);err != nil {
		return shim.Error("pustate error")
	}
	return shim.Success(companybytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:48
  @Desc:   自动还款 *
  @Param:  { time:string }
  @Return:
**/
func autoRepay(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//检测值
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	nowtime,err := time.Parse("2006-01-02",args[0])
	if err != nil {
		return shim.Error("time error")
	}
	//获取值
	result,err := stub.GetStateByPartialCompositeKey(TransactionKeyPrefix,[]string{})
	if err != nil {
		return shim.Error("getstate error")
	}
	defer result.Close()
	//遍历值
	for result.HasNext() {
		val,err := result.Next()
		if err != nil {
			return shim.Error("getstate error")
		}
		//反序列化
		var transation Transaction
		if err := json.Unmarshal(val.GetValue(),&transation);err != nil {
			return shim.Error("unmarshal error")
		}
		if transation.Status != TxStatusRepay && transation.Status != TxStatusRepayed {
			//检测自动还款
			if nowtime.Unix() > transation.RepayDate.Unix() {
				res := transferAccounts(stub,transation.Company,"buyer",transation.FinancialOrg,"financial_org",transation.Value)
				if res.Status != shim.OK {
					return shim.Error(res.Message)
				}
				//修改值
				transation.Status = TxStatusRepay
				transation.RepayDate = nowtime
				//创建主键
				compostieKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{transation.Id})
				if err != nil {
					return shim.Error("creat Key error")
				}
				//序列化值
				bytes,err := json.Marshal(transation)
				if err != nil {
					return shim.Error("marshal error")
				}
				//存回账本
				if err := stub.PutState(compostieKey,bytes);err != nil {
					return shim.Error("putstate error")
				}
			}
		}
	}
	return shim.Success(nil)
}

/**
  @Author: dd
  @Date:   2020/5/14 17:40
  @Desc:   验证公司是否存在 *
  @Param:  companyType:string, name:string
  @Return: bool，存在返回true，不存在返回false
**/
func valideCompany(stub shim.ChaincodeStubInterface, companyType string, name string) bool{
	//檢測值
	if companyType == "" || name == "" {
		return false
	}
	//創建主鍵
	compositekey,err := stub.CreateCompositeKey(companyType,[]string{name})
	if err != nil {
		return false
	}
	//获取值
	bytes,err := stub.GetState(compositekey)
	if err != nil {
		return false
	}
	if len(bytes) == 0 {
		return false
	}
	return true
}

/**
  @Author: dd
  @Date:   2020/5/14 17:41
  @Desc:   转账 从out转到in  *
  @Param:
  @Return:
**/
func transferAccounts(stub shim.ChaincodeStubInterface, out, outType, in, inType string, number uint64) pb.Response{
	if out == "" || outType == "" || in == "" || inType == "" || number == 0 {
		return shim.Error("invalid args")
	}
	//创建主键
	outcompositeKey,err := stub.CreateCompositeKey(outType,[]string{out})
	if err != nil {
		return shim.Error("createCompositeKey error")
	}
	incompositeKey,err := stub.CreateCompositeKey(inType,[]string{in})
	if err != nil {
		return shim.Error("createCompositeKey error")
	}
	//获取值
	outbyte,err := stub.GetState(outcompositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(outbyte) == 0 {
		return shim.Error("this company doesn't exist")
	}
	//获取值
	inbyte,err := stub.GetState(incompositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(inbyte) == 0 {
		return shim.Error("this company doesn't exist")
	}
	//反序列化值
	var outcompany Company
	var incompany Company

	if err := json.Unmarshal(outbyte,&outcompany);err != nil {
		return shim.Error("unmarshal error")
	}
	if err := json.Unmarshal(inbyte,&incompany);err != nil {
		return shim.Error("unmarshal error")
	}
	//转账
	outcompany.Balance -= number
	if outcompany.Balance < 0 {
		return shim.Error("out balance is not enough")
	}
	incompany.Balance += number
	//序列化值
	outbyte,err = json.Marshal(outcompany)
	if err != nil {
		return shim.Error("marshal error")
	}
	inbyte,err = json.Marshal(incompany)
	if err != nil {
		return shim.Error("marshal error")
	}
	//把值根据主键存账本
	if err := stub.PutState(outcompositeKey,outbyte);err != nil {
		return shim.Error("putstate error")
	}
	if err := stub.PutState(incompositeKey,inbyte);err != nil {
		return shim.Error("putstate error")
	}

	return shim.Success(nil)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:45
  @Desc:   根据企业类型获取企业信息 *
  @Param:  companyType:string 企业类型
  @Return: companys:[]Company
**/
func getCompany(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	companyType := args[0]
	if companyType == "" {
		return shim.Error("invalid args")
	}
	//从账本获取值
	result,err := stub.GetStateByPartialCompositeKey(companyType,[]string{})
	if err != nil {
		return shim.Error("getstate error")
	}
	defer result.Close()
	var companys []Company
	//遍历值
	for result.HasNext() {
		val,err := result.Next()
		if err != nil {
			return shim.Error("getstate error")
		}
		//反序列值
		var company Company
		if err := json.Unmarshal(val.GetValue(),&company);err != nil {
			return shim.Error("unmrshal error")
		}
		companys = append(companys, company)
	}
	//序列化值
	companysbytes,err := json.Marshal(companys)
	if err != nil {
		return shim.Error("marshal error")
	}
	return shim.Success(companysbytes)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:37
  @Desc:   获取买方的交易信息 *
  @Param:  buyer 买方公司名
  @Return: {transactions:[]Transaction,unfinished:int,total:int,violateTreaty:int}
			分别为此买方的交易信息、未完成交易数、交易总数、违约交易数（实际还款时间RepayDate大于应还款时间RepaymentDate）
**/
func getTrByBuyer(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//校验数据正确性
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	companyName := args[0]
	if companyName == "" {
		return shim.Error("invalid args")
	}
	//从账本获取值
	result,err := stub.GetStateByPartialCompositeKey(TransactionKeyPrefix,[]string{})
	if err != nil {
		return shim.Error("getstate error")
	}
	defer result.Close()
	var transations []Transaction
	var unfinished,total,violateTreaty int
	//遍历值
	for result.HasNext() {
		val,err := result.Next()
		if err != nil {
			return shim.Error("getstate error")
		}
		//反序列值
		var transation Transaction
		if err := json.Unmarshal(val.GetValue(),&transation);err != nil {
			return shim.Error("unmrshal error")
		}
		//检测类别
		if transation.Company == companyName{
			total++
			if transation.Status == TxStatusConfirm || transation.Status == TxStatusNew || transation.Status == TxStatusRefusePay || transation.Status == TxStatusPayForAnother{
				unfinished++
			}
			if transation.RepayDate.Unix() > transation.RepaymentDate.Unix(){
				violateTreaty++
			}
			transations = append(transations,transation)
		}
	}
	//分类值
	data := make(map[string]interface{})
	data["transations"] = transations
	data["total"] = total
	data["unfinished"] = unfinished
	data["violateTreaty"] = violateTreaty
	//序列化值
	byte,err := json.Marshal(data)
	if err != nil {
		return shim.Error("marshal error")
	}
	//序列化值
	return shim.Success(byte)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:04
  @Desc:   获取交易信息  根据Id查询交易，不传数组则查询所有
  @Param:  [id0,id1] []string
  @Return: transactions []Transaction
**/
func getTransactions(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//检测值
	if len(args) > 1 {
		return shim.Error("args is not enough")
	}
	//总结构体数据
	var transations []Transaction
	//根据值长度判断
	if len(args) == 0 {
		//获取值
		result,err := stub.GetStateByPartialCompositeKey(TransactionKeyPrefix,[]string{})
		if err != nil {
			return shim.Error("getstate error")
		}
		//遍历值
		defer result.Close()
		for result.HasNext() {
			val,err := result.Next()
			if err != nil {
				return shim.Error("getstate error")
			}
			//反序列值
			var transation Transaction
			if err := json.Unmarshal(val.GetValue(),&transation);err != nil {
				return shim.Error("unmarshal error")
			}
			transations = append(transations, transation)
		}
	}else {
		//获取值
		var keys []string
		if err := json.Unmarshal([]byte(args[0]),&keys);err != nil{
			return shim.Error("unmarshal error")
		}
		//遍历查询值
		for _,v := range keys{
			compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{v})
			if err != nil {
				return shim.Error("createCompositeKey error")
			}
			//	获取值
			byte,err := stub.GetState(compositeKey)
			if err != nil {
				return shim.Error("getstate error")
			}
			if len(byte) == 0 {
				return shim.Error("this transation doesn't exist")
			}
			//反序列值
			var transation Transaction
			if err := json.Unmarshal(byte,&transation);err != nil {
				return shim.Error("unmarshal error")
			}
			transations = append(transations, transation)
		}
	}
	//序列化值
	byte,err := json.Marshal(transations)
	if err != nil {
		return shim.Error("marshal error")
	}
	return shim.Success(byte)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:07
  @Desc:   查询此交易的历史信息
  @Param:  id:string
  @Return:
**/
func getTransactionHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response{
	//检测值
	if len(args) != 1 {
		return shim.Error("args is not enough")
	}
	id := args[0]
	if id == "" {
		return shim.Error("args invalid")
	}
	//创建主键
	compositeKey,err := stub.CreateCompositeKey(TransactionKeyPrefix,[]string{id})
	if err != nil {
		return shim.Error("createCompositeKey error")
	}
	//获取值
	bytee,err := stub.GetState(compositeKey)
	if err != nil {
		return shim.Error("getstate error")
	}
	if len(bytee) == 0 {
		return shim.Error("this transation doesn't exist")
	}
	//获取历史记录
	result,err := stub.GetHistoryForKey(compositeKey)
	if err != nil {
		return shim.Error("get history error")
	}
	//遍历值
	defer result.Close()
	var buffer bytes.Buffer
	s := false
	buffer.WriteString("{")
	for result.HasNext(){
		val,err := result.Next()
		if err != nil {
			return shim.Error("gethistory error")
		}
		if s {
			buffer.WriteString(",")
		}
		buffer.WriteString("\"TxId\":")
		buffer.WriteString("\"")
		buffer.WriteString(val.TxId)
		buffer.WriteString("\"")

		buffer.WriteString(",\"value\":")
		if val.IsDelete{
			buffer.WriteString("null")
		}else {
			buffer.WriteString("\"")
			buffer.WriteString(val.TxId)
			buffer.WriteString("\"")
		}

		buffer.WriteString(",\"TimeStamp\":")
		buffer.WriteString("\"")
		buffer.WriteString(time.Unix(val.Timestamp.Seconds,int64(val.Timestamp.Nanos)).String())
		buffer.WriteString("\"")

		buffer.WriteString(",\"IsDelete\":")
		buffer.WriteString("\"")
		buffer.WriteString(strconv.FormatBool(val.IsDelete))
		buffer.WriteString("\"")
	}
	buffer.WriteString("}")

	return shim.Success(buffer.Bytes())
}

func main() {
	err := shim.Start(new(SupplyChainFinance))
	if err != nil {
		fmt.Printf("Error starting chaincode: %s", err)
	}
}